package ys.mihoyo.ymcc.service.impl;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import ys.mihoyo.ymcc.exception.BusinessException;
import ys.mihoyo.ymcc.result.JSONResult;
import ys.mihoyo.ymcc.util.AssertUtil;
import ys.mihoyo.ymcc.util.StrUtils;
import ys.mihoyo.ymcc.util.VerifyCodeUtils;
import ys.mihoyo.ymcc.domain.MessageSms;
import ys.mihoyo.ymcc.dto.SendSmsParamDto;
import ys.mihoyo.ymcc.feignclient.IUserFeignClient;
import ys.mihoyo.ymcc.service.IMessageSmsService;
import ys.mihoyo.ymcc.service.VerifyCodeService;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements VerifyCodeService {
    @Autowired
    private IUserFeignClient userFeignClient;

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private IMessageSmsService messageSmsService;

    private static final String KEY_REGI = "register:";
    private static final String KEY_BLACK = "blacklist:";
    private static final String KEY_BLACK_TURE = "blackTure:";

    @Override
    public String getImgCode(String key) {
        //使用工具类生成验证码
        String code = StrUtils.getComplexRandomString(4);
        System.out.println(code);
        //将验证码存入redis,3分钟过期
        redisTemplate.opsForValue().set(key,code,3, TimeUnit.MINUTES);
        //使用工具类生成图片验证码
        return VerifyCodeUtils.verifyCode(115,40,code);
    }

    @Override
    public void sendSmsCode(SendSmsParamDto sendSmsParamDto) {
        String imageCode = sendSmsParamDto.getImageCode();
        String imageCodeKey = sendSmsParamDto.getImageCodeKey();
        //判断手机号和图形验证码是否为空
        JSONResult jsonResult = userFeignClient.queryByPhone(sendSmsParamDto.getMobile());
        AssertUtil.isNotNull(jsonResult,"用户服务异常");
        //判断图形验证码是否过期
        Object o = redisTemplate.opsForValue().get(imageCodeKey);
        AssertUtil.isEqualsIgnoreCase(o.toString(),imageCode ,"验证码已经过期" );
        //判断手机是否注册
        Object data = jsonResult.getData();
        AssertUtil.isNull(data,"该手机号码已注册，请直接登录");
        //按照10分钟9次数据查看是否是骚扰访问，如果是加入道黑名单中
        //获取手机号
        Object phone = redisTemplate.opsForValue().get(KEY_REGI + sendSmsParamDto.getMobile());


        //在Redis中查看是否有过访问记录或者是否是黑名单
        Object blacklistTure = redisTemplate.opsForValue().get(KEY_BLACK_TURE + sendSmsParamDto.getMobile());
        //有就劝退
        AssertUtil.isNull(blacklistTure,"抱歉该账号在封禁中");

        Object blacklist = redisTemplate.opsForValue().get(KEY_BLACK + sendSmsParamDto.getMobile());
        //设置计数器
        Integer frequency = 1;
        //判断访问次数
        if (blacklist != null){
            frequency = Integer.parseInt(blacklist.toString());
            //redisTemplate.opsForValue().increment(KEY_BLACK + sendSmsParamDto.getMobile(), 1);
            //判断是否超过10次
            if (frequency>1){
                //超过10次加入黑名单
                redisTemplate.opsForValue().set(KEY_BLACK_TURE + sendSmsParamDto.getMobile(), "封禁中",2,TimeUnit.HOURS);
                throw new BusinessException("抱歉访问次数过于频繁，请2小时候再次访问");
            }
        }else {
            //第一次来
            redisTemplate.opsForValue().set(KEY_BLACK + sendSmsParamDto.getMobile(), frequency, 10, TimeUnit.MINUTES);
            //redisTemplate.opsForValue().increment(KEY_BLACK + sendSmsParamDto.getMobile(), 1);

        }
        redisTemplate.opsForValue().increment(KEY_BLACK + sendSmsParamDto.getMobile(), 1);


        //获取手机验证码
        Object phoneCodeObj = redisTemplate.opsForValue().get(KEY_REGI + sendSmsParamDto.getMobile()); //
        String code = null;
        if(phoneCodeObj == null){//第一次发送 or 过期了
            code = StrUtils.getRandomString(4);
        }else{//没有过期，后续获取
            //上一次的时间戳
            long oldTime = Long.parseLong(phoneCodeObj.toString().split(":")[1]);
            //获取当前系统的时间戳
            long newTime = System.currentTimeMillis();
            //这一次的请求距离上一次的请求还不到一分钟 => 一分钟之内发送了另外一次请求 => 违规操作【1.手动刷新页面 2.前端js代码禁用】
            if((newTime-oldTime)<1*5*1000){
                throw new BusinessException("请勿重复发送验证码");
            }
            code = phoneCodeObj.toString().split(":")[0];//就使用没有过期的那一个
        }

        //将手机验证码保存到redis
        redisTemplate.opsForValue().set("register:"+sendSmsParamDto.getMobile(),code+":"+System.currentTimeMillis(),10, TimeUnit.MINUTES);
        System.out.println(redisTemplate.opsForValue().get(KEY_REGI+sendSmsParamDto.getMobile()));
        //六：向手机号码发送短信验证码
        //SmsUtils.sendSms(phone,"验证码:"+code+",请在3分钟内使用!");
        System.out.println("验证码:"+code+",请在3分钟内使用!");
        //组装消息
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle("注册验证码");
        messageSms.setContent("您的验证码为:"+code+",请在3分钟内使用!");
        messageSms.setSendTime(new Date());
        messageSms.setPhone(sendSmsParamDto.getMobile());
        //获取请求对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //获取ip地址
        String remoteAddr = requestAttributes.getRequest().getRemoteAddr();
        messageSms.setIp(remoteAddr);
        messageSmsService.insert(messageSms);
    }
}
